#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>

#include "data_type.h"
#include "alloc.h"
#include "memfunc.h"
#include "json.h"
#include "struct_deal.h"
#include "crypto_func.h"
#include "basefunc.h"
#include "memdb.h"
#include "message.h"
#include "connector.h"
#include "ex_module.h"
#include "channel.h"
#include "sys_func.h"

#include "mac_label.h"
#include "xkrnl_ctrl.h"
#include "xKrnl_policytrans.h"

#define MAX_LINE_LEN 1024

static unsigned char Buf[DIGEST_SIZE*128];
static BYTE * ReadBuf=Buf;
static int readbuf_len=0;
static BYTE * WriteBuf=Buf+DIGEST_SIZE*64;
static int write_len=0;

static int index = 0;
static char errorbuf[1024];
static unsigned char sendbuf[4096];
static CHANNEL * xKrnl_policytrans;
static void * extend_template;

void * head_template;
void * out_template;

int xKrnl_policytrans_init(void * sub_proc,void * para)
{
    int ret;
    struct xKrnl_policytrans_init_para * init_para=para;
    if(para==NULL)
	    return -EINVAL;
    xKrnl_policytrans=channel_find(init_para->channel_name);

    if(xKrnl_policytrans==NULL)
	    return -EINVAL;	
    
    head_template=memdb_get_template(TYPE_PAIR(XKRNL_CTRL,CTL_HEAD));
    if(head_template==NULL)
        return -EINVAL;

    return 0;
}

int xKrnl_policytrans_start(void * sub_proc,void * para)
{
    int ret = 0, len = 0, i = 0, j = 0;
    int rc = 0;

    int offset=0;	
    int readbuf_len=0;
    int record_len=0;
	BYTE local_uuid[DIGEST_SIZE];	
    ret=proc_share_data_getvalue("uuid",local_uuid);
	if(ret<0)
		return ret;
    void * record_struct;
    void * send_msg;
    void * recv_msg;

    RECORD(MAC_LABEL,CTL_HEAD) ctl_head;
    RECORD(MAC_LABEL,AUDIT_HEAD) audit_head;
    void * record_template;

    while(1)
    {
        usleep(time_val.tv_usec*10);
	    ret=channel_read(xKrnl_policytrans,ReadBuf,DIGEST_SIZE*64);
	    if(ret<0)
		    return ret;
        offset=0;
	    if(ret>0)
	    {
		    print_cubeaudit("xKrnl_policytrans read data %d",ret);
            readbuf_len =ret;
                    
            ret=blob_2_struct(ReadBuf,&ctl_head,head_template);
            if(ret<=0)
                return -EINVAL;

            offset+=ret;
            if(ctl_head.cntLen==0)
                continue;
            while(offset<readbuf_len)
            {

                record_template=memdb_get_template(TYPE_PAIR(MAC_LABEL,AUDIT_HEAD));
                if(record_template==NULL)
                     return -EINVAL;

                ret=blob_2_struct(ReadBuf+offset,&audit_head,record_template);
                if(ret<=0)
                    return -EINVAL;
            
                offset+=ret;    

                record_template=memdb_get_template(TYPE_PAIR(MAC_LABEL,FILE_EVENT));
                if(record_template==NULL)
                     return -EINVAL;

                record_struct = Talloc0(struct_size(record_template));
                if(record_struct==NULL)
                    return -ENOMEM;
                ret=blob_2_struct(ReadBuf+offset,record_struct,record_template);
                if(ret<0)
                {
                    if(readbuf_len-offset > 1440)
                        return -EINVAL;
                }
			    offset+=ret;
                send_msg=message_create(TYPE_PAIR(MAC_LABEL,FILE_EVENT),NULL);
                message_add_record(send_msg,record_struct);
                ex_module_sendmsg(sub_proc,send_msg);
            }
            if(offset>0)
            {
                Memcpy(ReadBuf,ReadBuf+offset,readbuf_len-offset);
                readbuf_len-=offset;
            }
		}
					
     	if((ex_module_recvmsg(sub_proc,&recv_msg)>=0)
		&&(recv_msg!=NULL))
     	{
            i=0;
            offset=0;
            while(message_get_record(recv_msg,&record_struct,i++)>=0)
            {
                if(record_struct==NULL)
                    break;
                ret=struct_2_blob(record_struct,WriteBuf+offset,head_template);
                if(ret<0)
                    return -EINVAL;
                offset+=ret;
            } 
	   	 	len=channel_write(xKrnl_policytrans,WriteBuf,offset);
            if (len != offset)
                print_cubeerr("xKrnl_policytrans write failed!\n");
			else
				print_cubeaudit("xKrnl_policytrans write %d data",offset);
        }
    }
    return 0;
}
